#ifndef MEDIAPLAYER_H
#define MEDIAPLAYER_H

#include <string>
#include "Thread.h"
#include "Mutex.h"
#include "Demuxer.h"
#include "Decoder.h"
#include "PacketQueue.h"
#include "FrameQueue.h"
#include "MessageQueue.h"

extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libswresample/swresample.h"
#include "libavutil/avutil.h"
#include "libavutil/time.h"
#include "libavutil/opt.h"

#include "libavutil/channel_layout.h"
#include "libavutil/samplefmt.h"
#include "libavfilter/avfilter.h"
#include "libavfilter/buffersink.h"
#include "libavfilter/buffersrc.h"
}

#ifdef RK
#include <drm.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <drm_fourcc.h>
#include "DRMVideoSink.h"
#else
#include "SDLVideoSink.h"
#endif
#include "AlsaAudioSink.h"

#include "Options.h"

using namespace std;

#define Ret_If_State_Eq(expected) \
    do { \
        if ((m_State) == (expected)) { \
        	LOGW("already in a %s state", getStateName(m_State)); \
        	return ; \
        }\
    } while(0)

typedef enum{
	Player_State_Idle = 0,
	Player_State_Initialized,
	Player_State_Async_Preparing,
	Player_State_Prepared,
	Player_State_Started,
	Player_State_Paused,
	Player_State_Completed,
	Player_State_Stoped,
	Player_State_Error,
	Player_State_End
}Player_State;

typedef enum {
	/*通知事件*/
	Player_Evt_Flush = 0,
	Player_Evt_Error,
	Player_Evt_PrePared,
	Player_Evt_Completed,
	Player_Evt_SeekCompleted,
	Player_Evt_OpenInput,
	Player_Evt_FindStreamInfo,
	Player_Evt_VideoChanged,
	Player_Evt_VideoRenderStart,
	Player_Evt_AudioRenderStart,

	/*操作事件*/
	Player_Evt_Seek,
	Player_Evt_Pause,
	Player_Evt_Start
}Player_Event;

typedef enum {
	Player_Error_DemuxOpen = 10000,
	Player_Error_DecoderOpen,
	Player_Error_AudioInit
}Player_Error;

typedef enum {
	Player_Property_Unkown,
	Player_Property_Float_PlayBackRate = 0,
	Player_Property_Float_AVDiff,
	Player_Property_Float_DropFrameRate,
	Player_Property_Float_FPS,
	Player_Property_Int_PlayBackVolume,
	Player_Property_Int_VideoDecoder,
	Player_Property_Int_VideoCachedDuration,
	Player_Property_Int_VideoCachedBytes,
	Player_Property_Int_VideoCachedPackets,

	/*视频解码参数*/
	Player_Property_Int_VideoHeight,
	Player_Property_Int_VideoWidth,
	Player_Property_Int_VideoFormat,
	Player_Property_Int_VideoBitRate,

	Player_Property_Int_AudioStream,
	Player_Property_Int_AudioDecoder,
	Player_Property_Int_AudioCachedDuration,
	Player_Property_Int_AudioCachedBytes,
	Player_Property_Int_AudioCachedPackets,

	/*音频解码参数*/
	Player_Property_Int_AudioSampleRate,
	Player_Property_Int_AudioChannels,
	Player_Property_Int_AudioChannelLayout,
	Player_Property_Int_AudioFormat,
	Player_Property_Int_AudioBitRate,
	Player_Property_Int_AudioFrameSize, //每一帧avframe包含的采样点数

	Player_Property_Int_Duration,
}Player_Property;

typedef enum {
	Audio_Operate_Unkown,
	Audio_Operate_Init,
	Audio_Operate_Pause,
	Audio_Operate_Play,
	Audio_Operate_Flush,
	Audio_Operate_SetSpeed,
	Audio_Operate_GetBufferDuration
}Audio_Operate_Func;

/* ffmpeg音频滤镜(类似于gstreamer的pipeline)
   The filter chain it uses is:
 * (input) -> abuffer -> volume -> aformat -> abuffersink -> (output)
 */
typedef struct audioFilterGraph {
    AVFilterGraph   *filter_graph;
    AVFilterContext *abuffer_ctx;
    const AVFilter  *abuffer;
    AVFilterContext *volume_ctx;
    const AVFilter  *volume;
    AVFilterContext *aformat_ctx;
    const AVFilter  *aformat;
    AVFilterContext *abuffersink_ctx;
    const AVFilter  *abuffersink;
}audioFilterGraph;

class MediaPlayer {

public:

	MediaPlayer();
	virtual ~MediaPlayer();

	void setDataSource(const char *url);
	void prepareASync();
	void start();
	void stop();
	void seek(int second);
	void pause();
	bool isPlaying();
	int getCurrentPosition(){return (int)(m_CurrentAudioPts*1000);} //ms
	int getDuration(){return m_PDemux->m_Duration;}
	void release();
	void reset();
	void setVolume(int volume);
	int getVolume(){return m_Volume;}
	// string getColorFormatName(){}
	// string getVideoCodecInfo(){}
	// string getAudioCodecInfo(){}
	typedef void (*player_callback)(void *player, Player_Event evt);
	void registerEventCallback(void *player, Player_Event evt){}

	void setOption(const char *key, int value);
	void setOption(const char *key, const char *value);
	void showOption();
	void showOpts();

	float getPropertyFloat(Player_Property id);
	int getPropertyInt(Player_Property id);

	static int msgLoopThread(void *lpara);
	static int demuxThread(void *lpara);
	static int videoDecodeThread(void *lpara);
	static int audioDecodeThread(void *lpara);
	static int videoRefreshThread(void *lpara);
	static int audioOutThread(void *lpara);
	static int decode_interrupt_cb(void *ctx);

	int message_loop();
	int demux_thread();
	int video_decode();
	int audio_decode();
	int video_refresh();
	int audio_out();

	/*外部提供的显示一帧图像的函数*/
	typedef int (*videodisplay_callback)(Frame *frame, void *ctx);
	void registerVideoDisplayCB(videodisplay_callback video_discb, void *ctx);

	typedef int (*videoinit_callback)(void *ctx, void *lpara);
	void registerVideoInitCB(videoinit_callback video_init, void *lpara);

	typedef void (*event_callback)(Message *msg, void *ctx);
	void registerEventCB(event_callback eventcb, void *ctx);

	void postEvent(Player_Event evt, int arg1 = 0, int arg2 = 0);

	/*提供给外部，用于获取解码后的音频Frame帧*/
	Frame *getAudioFrame();
	/*外部提供的音频相关接口*/
	typedef void (*audio_operate_callback)(void *ctx, void *lpara);
	void registerAudioOperateCB(Audio_Operate_Func operate, audio_operate_callback func, void *lpara = NULL);

	/*外部提供的播放一帧音频的函数*/
	typedef int (*audioout_callback)(unsigned char *data, int size, void *ctx);
	void registerAudioOutCB(audioout_callback audio_outcb, void *ctx);

	/*内部调用，用于统一调用外部音频操作接口*/
	void audioOperate(Audio_Operate_Func operate, void *lpara = NULL);

	/*音视频同步相关*/
	void setAudioPts(double pts);

	/*初始化ffmpeg滤镜图*/
	int initAudioFilterGraph(int in_sample_rate, int in_format, int in_channel_layout, \
							int out_sample_rate, int out_format, int out_channel_layout);

	/*使用videoSink显示一帧图像*/
	int displayImage(Frame *frame);
	void setDisplayArea(int x, int y, int w, int h);

	/*视频显示控制*/
	void videoShow();
	void videoHide();
protected:
	void init();
	void changeToState(Player_State state);
	void playerAbortRequest();

	void handle_msg_internal(Message &msg);
	void call_external_cb(Message &msg);

	void bufferingControl();

	const char* getStateName(Player_State state);
	const char* getEventName(Player_Event evt);
	const char* getErrorInfo(Player_Error err);

	static void logCallBack(void *ptr, int level, const char *fmt, va_list vl);

public:
	Player_State m_State;
	string m_Url;
	// char *m_Url;
	Thread *m_PMsgThread;
	Thread *m_PDemuxThread;
	Thread *m_PVideoDecodeThread;
	Thread *m_PAudioDecodeThread;
	Thread *m_PVideoRefreshThread;
	Thread *m_PAudioOutThread;

	PacketQueue *m_PVideoPacketQueue;
	PacketQueue *m_PAudioPacketQueue;

	FrameQueue *m_PVideoFrameQueue;
	FrameQueue *m_PAudioFrameQueue;

	MessageQueue *m_PMsgQueue;

	Mutex m_PlayerMutex;
	bool m_PlayerAbortRequest;

	bool m_Prepared;

	videodisplay_callback m_VideoDisCB;
	void *m_VideoDisPara;

	videoinit_callback m_VideoInitCB;
	void *m_VideoInitPara;

	audioout_callback m_AudioOutCB;
	void *m_AudioOutPara;

	event_callback m_EventCB;
	void *m_EventPara;

	audio_operate_callback m_AudioFuncInit;
	audio_operate_callback m_AudioFuncPause;
	audio_operate_callback m_AudioFuncPlay;
	audio_operate_callback m_AudioFuncFlush;
	audio_operate_callback m_AudioFuncSetSpeed;
	audio_operate_callback m_AudioFuncGetBufferDuration;
	void *m_AudioCBPara;
	void *m_AudioInitPara;

protected:
	Demuxer *m_PDemux;
	Decoder *m_PVideoDecoder;
	Decoder *m_PAudioDecoder;

	/*音频格式转换 换成libavfilter，和音量调节一起使用滤镜图*/
	struct SwrContext *m_AudioConvertCtx;
	unsigned char *m_AudioBuff;
	int m_AudioOutBuffSize;

	/*控制相关*/
	bool m_SeekRequest;
	int m_SeekPos;
	bool m_PauseRequest;
	bool m_Restart;
	bool m_VideoHide;

	int m_Volume;

	/*音视频同步相关*/
	double m_CurrentAudioPts; //Second
	double m_FrameTimer;

	/*options结构*/
	PlayerOptions m_PlayerOpt;

	/*音频滤镜 调节音量*/
	audioFilterGraph m_AudioFilter;

	/*buffer control*/
	bool m_IsBuffering;

	bool m_AudioPktUnderrun;

	//音视频输出
	VideoSink *m_PVideoSink;
	AlsaAudioSink *m_PAudioSink;
	bool m_FirstVideoRendered;
	bool m_FirstAudioRendered;

	/*视频参数*/
	int m_Width;
	int m_Height;

	/*音频参数*/
	int m_AudioFmt;
	int m_AudioChannelLayout;
	int m_AudioSampleRate;
	int m_Channels;
};

#endif